package com.oneToMany.bothway.servcie;

import com.oneToMany.bothway.model.Customer;
import com.oneToMany.bothway.model.Order;
import com.utils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import java.util.HashSet;
import java.util.Set;

public class BusinessService {

    private SessionFactory sessionFactory = new HibernateUtil().getSessionFactory();
    private Long idOfTom;
    private Long idOfTomOrder;
    private Long idOfJack;
    private Long idOfJackOrder;

    private void printOrdersOfCustomer(Long customerId) {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Customer customer = (Customer) session.get(Customer.class, customerId);
            printOrders(customer.getOrders());
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            throw e;
        } finally {
            session.close();
        }
    }

    private void saveCustomerAndOrderWithCascade() {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();

            Customer customer = new Customer("Tom", new HashSet<Order>());
            Order order = new Order();
            order.setOrderNumber("Tom_Order001");

            order.setCustomer(customer);
            customer.getOrders().add(order);

            session.save(customer);
            tx.commit();
            idOfTom = customer.getId();
            idOfTomOrder = order.getId();

        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    private void associateCustomerAndOrder() {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Customer customer = (Customer) session.load(Customer.class, idOfJack);
            Order order = (Order) session.load(Order.class, idOfJackOrder);
            order.setCustomer(customer);
            customer.getOrders().add(order);
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    private void saveCustomerAndOrderSeparately() {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();

            Customer customer = new Customer();
            customer.setName("Jack");

            Order order = new Order();
            order.setOrderNumber("Jack_Order001");

//            customer.getOrders().add(order);
//            order.setCustomer(customer);
            session.save(customer);
            session.save(order);

            tx.commit();
            idOfJack = customer.getId();
            idOfJackOrder = order.getId();
        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    private void deleteCustomer(Long customerId) {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Customer customer = (Customer) session.load(Customer.class, customerId);
            session.delete(customer);
            tx.commit();

        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    private void removeOrderFromCustomer(Long customerId) {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Customer customer = (Customer) session.load(Customer.class, customerId);
            System.out.println(customer.toString());
            Order order = customer.getOrders().iterator().next();

            customer.getOrders().remove(order);
            order.setCustomer(null);
            tx.commit();

        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    private void printOrders(Set orders) {
        for (Object order1 : orders) {
            Order order = (Order) order1;
            System.out.println("OrderNumber of " + order.getCustomer().getName() + " :" + order.getOrderNumber());
        }
    }

    private void saveCustomerAndOrderWithInverse() {
        saveCustomerAndOrderSeparately();
        associateCustomerAndOrder();
    }
    private void test() {

        saveCustomerAndOrderWithCascade();
        saveCustomerAndOrderWithInverse();
        printOrdersOfCustomer(idOfTom);
        deleteCustomer(idOfJack);
        removeOrderFromCustomer(idOfTom);
        sessionFactory.close();
    }

    public static void main(String args[]) {
        new BusinessService().test();
    }
}


